package com.xiran.srpingboottemplateself.config;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Redis配置类
 * 功能：自定义RedisTemplate的序列化方式，解决默认JDK序列化的缺陷
 * 解决问题：
 * 1. 默认JDK序列化导致Redis中数据可读性差
 * 2. 序列化后的数据体积较大，占用更多存储空间
 * 3. 反序列化时可能出现类型转换问题
 */
@Configuration // 标识为Spring配置类，会被自动扫描加载
@Slf4j // Lombok注解，提供日志输出能力
public class RedisConfiguration {


    private static final long serialVersionUID = 3191241716373120712L;

    /**
     * 字符串序列化器
     * 用于Redis的key和hash结构的field序列化
     */
    private static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer();

    /**
     * JSON序列化器
     * 用于Redis的value和hash结构的value序列化
     * 将Java对象序列化为JSON字符串，提高可读性
     */
    private static final Jackson2JsonRedisSerializer<Object> JSON_SERIALIZER;

    // 静态代码块：初始化JSON序列化器
    static {
        // 创建Jackson的核心处理类ObjectMapper
        ObjectMapper objectMapper = new ObjectMapper();

        // 配置序列化时保留类型信息（解决反序列化时的类型识别问题）
        // 例如：List<User>反序列化时能正确识别为List而非普通Collection
        objectMapper.activateDefaultTyping(
                objectMapper.getPolymorphicTypeValidator(),
                ObjectMapper.DefaultTyping.NON_FINAL, // 对非final类型生效
                JsonTypeInfo.As.PROPERTY // 类型信息以属性形式存储（默认字段为@class）
        );

        // 初始化JSON序列化器，指定处理的目标类型为Object（支持任意类型）
        JSON_SERIALIZER = new Jackson2JsonRedisSerializer<>(Object.class);
        // 为序列化器设置自定义的ObjectMapper
        JSON_SERIALIZER.setObjectMapper(objectMapper);
    }

    /**
     * 自定义RedisTemplate Bean
     * 替代Spring默认提供的RedisTemplate，使用字符串+JSON的序列化组合
     *
     * @param factory Redis连接工厂（由Spring根据配置文件自动创建）
     * @return 配置完成的RedisTemplate实例
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        log.info("开始初始化自定义RedisTemplate");

        // 创建RedisTemplate实例，指定key为String类型，value为Object类型
        RedisTemplate<String, Object> template = new RedisTemplate<>();

        // 设置Redis连接工厂
        template.setConnectionFactory(factory);

        // 配置key的序列化方式：字符串序列化
        template.setKeySerializer(STRING_SERIALIZER);
        // 配置hash结构中field的序列化方式：字符串序列化
        template.setHashKeySerializer(STRING_SERIALIZER);


        // 配置value的序列化方式：JSON序列化
        template.setValueSerializer(JSON_SERIALIZER);
        // 配置hash结构中value的序列化方式：JSON序列化
        template.setHashValueSerializer(JSON_SERIALIZER);

        // 初始化模板配置
        template.afterPropertiesSet();

        log.info("自定义RedisTemplate初始化完成");
        return template;
    }
}
